package com.jpro.framework.quartz.client.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.jpro.framework.common.util.json.JsonUtils;
import com.jpro.framework.quartz.client.vo.JobGroupResponse;
import com.jpro.framework.quartz.client.vo.JobInfo;
import com.jpro.framework.quartz.client.vo.JobInfoResponse;
import com.jpro.framework.quartz.client.vo.XxlJobInfo;
import com.jpro.framework.quartz.config.XxlJobProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;

import java.net.HttpCookie;
import java.util.HashMap;
import java.util.Map;

import static com.jpro.framework.common.exception.enums.GlobalErrorCodeConstants.ERROR_XXL_SERVER;
import static com.jpro.framework.common.pojo.CommonResult.error;

/**
 * 调度通用类
 */
public class ScheduleUtil {

    public static final String COMMA = ",";

    private static final Logger log = LoggerFactory.getLogger(ScheduleUtil.class);

    /**
     * 调度中心地址
     **/
    private static String adminAddresses;
    /**
     * 执行器名称
     **/
    private static String appname;
    /**
     * 用户名
     **/
    private static String username;
    /**
     * 密码
     **/
    private static String password;

    public ScheduleUtil(XxlJobProperties xxljobProperties) {
        if (xxljobProperties == null) {
            log.error("ScheduleUtil init error, the xxljobProperties is null");
        } else {
            adminAddresses = xxljobProperties.getAdmin().getAddresses();
            appname = xxljobProperties.getExecutor().getAppName();
            username = xxljobProperties.getAdmin().getUsername();
            password = xxljobProperties.getAdmin().getPassword();
        }

    }

    /**
     * 获取注册中心地址
     **/
    public static String getUrl() {
        String pathUrl = null;
        if (!ObjectUtils.isEmpty(adminAddresses)) {
            if (adminAddresses.contains(COMMA)) {
                String[] split = adminAddresses.split(COMMA);
                //发送测试，去除不在线的注册中心
                for (String url : split) {
                    String urls = checkUrl(url);
                    if (!ObjectUtils.isEmpty(urls)) {
                        pathUrl = urls;
                        break;
                    }
                }
            } else {
                pathUrl = checkUrl(adminAddresses);
            }
        }
        if (ObjectUtils.isEmpty(pathUrl)) {
//            throw new RuntimeException("获取xxljob url失败");
            log.error("获取xxljob url失败");
            error(ERROR_XXL_SERVER);
        }
        return pathUrl;
    }


    /**
     * 检测URL
     *
     * @param url 连接
     * @return String
     */
    private static String checkUrl(String url) {
        try {
            HttpRequest get = HttpUtil.createGet(url);
            get.setMethod(Method.OPTIONS);
            HttpResponse execute = get.execute();
            if (execute.getStatus() < 500) {
                return url;
            }
        } catch (Exception ignored) {
            log.debug("The URL is not used");
        }
        return null;
    }

    /**
     * 登录
     *
     * @return String
     */
    private static HttpCookie login() {
        String url = getUrl() + "/login" + "?userName=" + username + "&password=" + password;
        HttpRequest post = HttpUtil.createPost(url);
        try {
            HttpResponse response = post.execute();
            if (response.isOk()) {
                return response.getCookie("XXL_JOB_LOGIN_IDENTITY");
            }
        } catch (Exception e) {
            error(ERROR_XXL_SERVER);
            log.error("登录失败 -> login error");
        }
        log.error("登录失败 -> login error");
        return null;
    }

    /**
     * 获取执行器ID
     *
     * @return Integer
     */
    public static Integer getGroupId() {
        String path = getUrl();
        HttpCookie cookie = login();
        if (path != null && cookie != null) {
            String targetUrl = path + "/jobgroup/pageList";
            Map<String, Object> paramMap = new HashMap<>(10);
            paramMap.put("appname", appname);
            String jobResponse = HttpUtil.get(targetUrl, paramMap);
            JobGroupResponse response = JsonUtils.parseObject(jobResponse, JobGroupResponse.class);
            if (response != null) {
                if (response != null && !response.getData().isEmpty()) {
                    return response.getData().get(0).getId();
                } else {
                    log.error("获取groupId失败");
                    throw new RuntimeException("获取groupId失败");
                }
            } else {
                log.error("getGroupId error");
                throw new RuntimeException("getGroupId error");
            }
        }
        return null;
    }

    /**
     * 新增任务
     *
     * @param info 新增参数
     * @return 任务ID
     */
    public static Integer addJob(JobInfo info) {
        String path = getUrl();
        Integer groupId = getGroupId();
        if (path != null && groupId != null) {
            //校验
            if (!info.getRepJobHandler()) {
                boolean flag = validJobHandler(info.getExecutorHandler());
                if (flag) {
                    throw new RuntimeException(
                            "新增任务失败，存在相同的执行器名称 -> New task failed, same executor name exists");
                }
            }
            String targetUrl = path + "/jobinfo/add";
            HttpUtil.createPost(targetUrl);
            XxlJobInfo xxlJobInfo = new XxlJobInfo(info, groupId);
            String jobResponse = HttpUtil.post(targetUrl, BeanUtil.beanToMap(xxlJobInfo));
            JobInfoResponse response = JsonUtils.parseObject(jobResponse, JobInfoResponse.class);
            if (response != null) {
                if (JobInfoResponse.SUCCESS.equals(response.getCode())) {
                    return Integer.valueOf(response.getContent());
                } else {
                    log.error(response.getMsg());
                    throw new RuntimeException((response.getMsg()));
                }
            } else {
                log.error("addJob error");
                throw new RuntimeException("addJob error");
            }
        } else {
            log.error("调度中心尚未提供服务 -> The dispatch center is not yet in service");
            throw new RuntimeException("调度中心尚未提供服务 -> The dispatch center is not yet in service");
        }
    }

    /**
     * 编辑任务
     *
     * @param info 新增参数
     */
    public static void updateJob(JobInfo info) {
        String path = getUrl();
        HttpCookie cookie = login();
        if (path != null && cookie != null) {
            XxlJobInfo xxlJobInfo = new XxlJobInfo(info, getGroupId());
            String targetUrl = path + "/jobinfo/update";
            String jobResponse = HttpUtil.post(targetUrl, BeanUtil.beanToMap(xxlJobInfo));
            JobInfoResponse response = JsonUtils.parseObject(jobResponse, JobInfoResponse.class);
            if (response != null) {
                if (JobInfoResponse.SUCCESS.equals(response.getCode())) {
                    log.info("update job :{} success", info.getId());
                } else {
                    log.error(response.getMsg());
                    throw new RuntimeException((response.getMsg()));
                }
            } else {
                log.error("updateJob error");
//                throw new RuntimeException("updateJob error");
                error(ERROR_XXL_SERVER);
            }
        }
    }

    public static XxlJobInfo getById(Integer id) {
        if (id == null) {
            return null;
        }
        String path = getUrl();
        HttpCookie cookie = login();
        if (path != null && cookie != null) {
            String targetUrl = path + "/jobinfo/getById?id=" + id;
            String jobResponse = HttpUtil.get(targetUrl);
            JobInfoResponse response = JsonUtils.parseObject(jobResponse, JobInfoResponse.class);
            if (response != null) {
                if (JobInfoResponse.SUCCESS.equals(response.getCode())) {
                    log.info("getById job :{} success", id);
                    String data = response.getContent();
                    if (!ObjectUtils.isEmpty(data)) {
                        return JsonUtils.parseObject(data, XxlJobInfo.class);
                    }
                } else {
                    log.error(response.getMsg());
                    throw new RuntimeException((response.getMsg()));
                }
            } else {
                log.error("getById error");
                throw new RuntimeException("getById error");
            }
        }
        return null;
    }

    /**
     * 删除任务
     *
     * @param id 任务ID
     */
    public static void deleteJob(Long id) {
        String path = getUrl();
        HttpCookie cookie = login();
        if (path != null && cookie != null) {
            String targetUrl = path + "/jobinfo/remove?id=" + id;
            String jobResponse = HttpUtil.get(targetUrl);
            JobInfoResponse response = JsonUtils.parseObject(jobResponse, JobInfoResponse.class);
            if (response != null) {
                if (JobInfoResponse.SUCCESS.equals(response.getCode())) {
                    log.info("delete job :{} success", id);
                } else {
                    log.error(response.getMsg());
                    throw new RuntimeException((response.getMsg()));
                }
            } else {
                log.error("deleteJob error");
                error(ERROR_XXL_SERVER);
//                throw new RuntimeException("deleteJob error");
            }
        }

    }

    /**
     * 开始任务
     *
     * @param id 任务ID
     */
    public static void startJob(int id) {
        String path = getUrl();
        HttpCookie cookie = login();
        if (path != null && cookie != null) {
            String targetUrl = path + "/jobinfo/start?id=" + id;
            String result = HttpUtil.get(targetUrl);
            if (result == null) {
                log.error("启动定时任务失败，任务id:{}", id);
                throw new RuntimeException("启动定时任务失败");
            }
            JobInfoResponse response = JsonUtils.parseObject(result, JobInfoResponse.class);
            if (response != null) {
                if (JobInfoResponse.SUCCESS.equals(response.getCode())) {
                    log.info("start job :{} success", id);
                } else {
                    log.error(response.getMsg());
                    throw new RuntimeException(response.getMsg());
                }
            } else {
                log.error("startJob error");
                throw new RuntimeException("startJob error");
            }

        }
    }

    /**
     * 停止任务
     *
     * @param id 任务ID
     */
    public static void stopJob(int id) {
        String path = getUrl();
        HttpCookie cookie = login();
        if (path != null && cookie != null) {
            String targetUrl = path + "/jobinfo/stop?id=" + id;
            String result = HttpUtil.get(targetUrl);
            if (result == null) {
                log.error("停止定时任务失败，任务id:{}", id);
                throw new RuntimeException("启动定时任务失败");
            }
            JobInfoResponse response = JsonUtils.parseObject(result, JobInfoResponse.class);
            if (response != null) {
                if (JobInfoResponse.SUCCESS.equals(response.getCode())) {
                    log.info("stop job :{} success", id);
                } else {
                    log.error(response.getMsg());
                    throw new RuntimeException((response.getMsg()));
                }
            } else {
                log.error("stopJob error");
                throw new RuntimeException("stopJob error");
            }
        }
    }

    /**
     * 校验jobhandler是否存在
     * true存在，false不存在
     *
     * @param jobHandler 任务执行器名称
     */
    public static boolean validJobHandler(String jobHandler) {
        String path = getUrl();
        HttpCookie cookie = login();
        if (path != null && cookie != null) {
            String targetUrl = path + "/jobinfo/valid?jobGroupId=" + getGroupId() + "&jobHandler="
                    + jobHandler;
            String jobResponse = HttpUtil.get(targetUrl);
            JobInfoResponse response = JsonUtils.parseObject(jobResponse, JobInfoResponse.class);
            if (response != null) {
                if (JobInfoResponse.SUCCESS.equals(response.getCode())) {
                    return Boolean.parseBoolean(response.getContent());
                } else {
                    log.error(response.getMsg());
                    throw new RuntimeException((response.getMsg()));
                }
            } else {
                log.error("validJobHandler error");
                throw new RuntimeException("validJobHandler error");
            }
        }
        return true;
    }

}